'''
@Description: In User Settings Edit
@Author: your name
@Date: 2019-08-13 17:14:46
@LastEditTime: 2019-10-10 15:53:24
@LastEditors: Please set LastEditors
'''

from server.pao_python.pao.service.data.mongo_db import MongoService, C, N, F, as_date
from ...service.buss_pub.bill_manage import BillManageService, OperationType, TypeId, Status
from ...service.common import get_current_role_id, insert_data, find_data, update_data, delete_data, get_condition, get_info, get_current_user_id, get_user_id_or_false, get_current_organization_id, get_serial_number, SerialNumberType
from ...pao_python.pao.service.security.security_service import RoleService
import hashlib
import re
import math
import datetime
import time
import uuid
import pandas as pd
import requests
import base64
from enum import Enum
from ...pao_python.pao.data import process_db, dataframe_to_list, DataProcess, DataList, get_cur_time
from ...service.mongo_bill_service import MongoBillFilter
import dateutil
import calendar
from ...service.buss_mis.operation_record import OperationRecordObject, OperationRecordType, OperationRecordService
from ...service.buss_pub.person_org_manage import PersonOrgManageService
from ...service.buss_pub.message_manage import MessageManageService, MessageState
# -*- coding: utf-8 -*-

'''
活动管理函数
'''


class Auditstatus(Enum):
    # 通过
    adopt = '通过'
    # 不通过
    reject = '不通过'
    # 待审批
    unaudited = '待审批'
    # 未拨款
    unpay = '未拨款'
    # 待审批拨款
    waitpayed = '待拨款'
    # 已拨款
    payed = '已拨款'

# 捐款使用状态


class Participate():
    '''活动参与对象'''

    def __init__(self, user_id, activity_id, date, status):
        '''构造函数'''
        # 用户ID
        self.user_id = user_id
        # 活动ID
        self.activity_id = activity_id
        # 参与时间
        self.date = date
        # 参与状态
        self.status = status

    def to_dict(self):
        return self.__dict__


class SignIn():
    '''活动签到对象'''

    def __init__(self, user_id, activity_id, date):
        '''构造函数'''
        # 用户ID
        self.user_id = user_id
        # 活动ID
        self.activity_id = activity_id
        # 签到时间
        self.date = date

    def to_dict(self):
        return self.__dict__


class ParticipateStatus(Enum):
    # 参与
    participate = 'participate'
    # 取消
    cancel = 'cancel'


class ActivityStatus(Enum):
    # 报名中
    enroll = 'enroll'
    # 进行中
    progress = 'progress'
    # 已截止
    finish = 'finish'
    # 已报名
    participate = 'participate'
    # 已完成
    complete = 'complete'
    # 已满员
    fully = 'fully'


class ActivityManageService(MongoService):
    ''' 活动管理 '''

    def __init__(self, db_addr, db_port, db_name, db_user, db_pwd, inital_password, session):
        DataProcess.__init__(self, db_addr, db_port, db_name, db_user, db_pwd)
        # self.db_name = db_name
        self.inital_password = inital_password
        self.session = session
        self.bill_manage_server = BillManageService(
            self.db_addr, self.db_port, self.db_name, self.db_user, self.db_pwd, self.inital_password, self.session)
        self.OperationRecordService = OperationRecordService(
            db_addr, db_port, db_name, db_user, db_pwd, inital_password, session)
        self.PersonOrgManageService = PersonOrgManageService(
            db_addr, db_port, db_name, db_user, db_pwd, inital_password, session)
        self.MessageManageService = MessageManageService(
            db_addr, db_port, db_name, db_user, db_pwd, inital_password, session)

    def setTest(self):
        _filter = MongoBillFilter()
        _filter.sort({'create_date': -1})\
            .project({'_id': 0})
        res = self.page_query(
            _filter, "PT_Activity", 1, 9999)
        for item in res.get('result'):
            data = {
                "define_id": "94dc3b2d-0b41-11ea-b83e-a0a4c57e9ebe",
                "business_id": item['id'],
                "approval_user_id": "8eaf3fba-e355-11e9-b97e-a0a4c57e9ebe",
                "step_no": 1,
                "opinion": [],
                "status": "通过",
                "organization_id": "7e7e2fec-d91d-11e9-8e1d-983b8f0bcd67",
                "id": str(uuid.uuid1()),
            }
            self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.activity.value, data, 'PT_Approval_Process')
            data1 = {
                "define_id": "94dc3b2d-0b41-11ea-b83e-a0a4c57e9ebe",
                "business_id": item['id'],
                "approval_user_id": "8eaf3fba-e355-11e9-b97e-a0a4c57e9ebe",
                "step_no": -1,
                "opinion": [],
                "status": "通过",
                "organization_id": "7e7e2fec-d91d-11e9-8e1d-983b8f0bcd67",
                "id": str(uuid.uuid1()),
            }
            self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.activity.value, data1, 'PT_Approval_Process')

    def convertDegreesToRadians(self, degrees):
        return degrees * math.pi / 180

    def coverGpsToBaiduLatLon(self, lat, lon):
        baidu_map_url = 'http://api.map.baidu.com/ag/coord/convert?from=0&to=4&x=%f&y=%f'

        data_req = requests.get((baidu_map_url % (lon, lat)))
        new_pos = data_req.json()
        if 'error' in new_pos.keys() and new_pos['error'] == 0:
            lon = float(base64.b64decode(
                new_pos['x']).decode("utf-8"))
            lat = float(base64.b64decode(
                new_pos['y']).decode("utf-8"))
            return lat, lon

    def get_activity_list(self, org_list, condition, page=None, count=None):
        '''查询活动列表'''
        keys = ['id', 'name', 'activity_name',
                'activity_type_id', 'begin_date', 'end_date', 'organization_id', 'lat', 'lon']

        # 判断是否登录
        user_id = get_user_id_or_false(self.session)

        activity_project = {'_id': 0,
                            'activity_type': 0,
                            'new_field': 0,
                            'process': 0,
                            'bill_status': 0,
                            'modify_date': 0,
                            'organ': 0,
                            'version': 0,
                            'valid_bill_id': 0,
                            'collection_info._id': 0,
                            'participate': 0}
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id']) &
                           (C('activity_type_id') == values['activity_type_id']) &
                           (C('organization_id') == values['organization_id']) &
                           (C('activity_name').like(values['activity_name'])) &
                           (C('organization_id').inner(org_list)))\
            .lookup_bill('PT_User', 'organization_id', 'id', 'organ')\
            .lookup_bill('PT_Activity_Participate', 'id', 'activity_id', 'participate')\
            .add_fields({'participate_count': self.ao.size('$participate'), })\
            .lookup_bill('PT_Service_Follow_Collection', 'id', 'business_id', 'collection_info')\
            .add_fields({'collection_count': self.ao.size('$collection_info'), })\
            .lookup_bill('PT_Activity_Type', 'activity_type_id', 'id', 'activity_type')\
            .add_fields({
                'organization_star': self.ao.array_elemat('$organ.organization_info.star_level', 0),
                'organization_lat': self.ao.array_elemat('$organ.organization_info.lat', 0),
                'organization_lon': self.ao.array_elemat('$organ.organization_info.lon', 0),
                'organization_name': self.ao.array_elemat('$organ.name', 0),
                'activity_type_name': self.ao.array_elemat('$activity_type.name', 0),
                'organization_address': self.ao.array_elemat('$organ.organization_info.address', 0)})

        if user_id != False:
            _filter.add_fields({'is_participate': self.ao.size(self.ao.array_filter(
                "$participate", "aa", ((F('$aa.user_id') == user_id)).f))})
            # 表示是我发布的
            if 'is_mine' in condition:
                _filter.match_bill((C('apply_user_id') == user_id))

        now_date = get_cur_time()
        # 判断活动状态的
        if 'status' in condition:
            # 报名中
            if condition['status'] == ActivityStatus.enroll.value:
                _filter.match_bill((C('begin_date') > now_date))
                _filter.add_fields({'c': self.ao.cond(
                    (F('participate_count') < F('max_quantity')).f, 1, 0)}).match((C('c') == 1))
            # 进行中
            elif condition['status'] == ActivityStatus.progress.value:
                _filter.match_bill((now_date >= C('begin_date'))
                                   & (C('end_date') >= now_date))
            # 已结束
            elif condition['status'] == ActivityStatus.finish.value:
                _filter.match_bill(now_date > C('end_date'))
            # 已满员
            elif condition['status'] == ActivityStatus.fully.value:
                _filter.add_fields({'c': self.ao.cond(
                    (F('participate_count') >= F('max_quantity')).f, 1, 0)}).match((C('c') == 1))

        # 活动时间内，开始时间大于开始范围或者结束时间小于结束范围都算吧
        if 'begin_date' in condition and 'end_date' in condition:
            _filter.match_bill((C('begin_date') >= condition['begin_date']) & (
                C('end_date') <= condition['end_date']))

        if 'all' not in condition:
            # 默认拿已经通过的
            condition_all = 'ts'
        else:
            condition_all = condition['all']
            del(condition['all'])

        print(condition)

        if condition_all == 'ts':
            # 推送列表只拿已经通过的的
            _filter.match_bill((C("step_no") == '-1') | (C("step_no") == -1))
            # activity_project['step_no'] = 0
            activity_project['apply_user_id'] = 0
            # activity_project['activity_type_id'] = 0
            activity_project['GUID'] = 0
            activity_project['sp_msg'] = 0
        elif condition_all == 'sh':
            # 审核列表只拿待审批的
            role_id = get_current_role_id(self.session)
            _filter.lookup_bill('PT_Approval_Process', 'id', 'business_id', 'process')\
                .add_fields({'new_field': self.ao.array_filter("$process", "aa", ((F('$aa.approval_user_id') == role_id) & (F('$aa.step_no') == (F('step_no'))) & (F('$aa.status') == '待审批')).f)}).match((C("new_field") != None) & (C("new_field") != []))

        if 'sort' in condition and condition['sort'] != None:
            if condition['sort'] == '距离' and 'lat' in condition and 'lon' in condition:
                lat = values['lat']
                lon = values['lon']
                # 纬度，经度
                lat_baidu, lon_baidu = self.coverGpsToBaiduLatLon(lat, lon)
                lat_d = self.convertDegreesToRadians(lat_baidu)
                _filter.filter_objects.append({
                    '$addFields': {
                        # 距离是以km单位的
                        "distance": {
                            '$multiply': [
                                {
                                    '$acos': {
                                        '$add': [
                                            {
                                                '$multiply': [
                                                    {
                                                        '$sin': {'$degreesToRadians': {"$toDouble": "$organization_info.lat"}}
                                                    },
                                                    {
                                                        '$sin': lat_d
                                                    }
                                                ]
                                            },
                                            {
                                                '$multiply': [
                                                    {
                                                        '$cos': {'$degreesToRadians': {"$toDouble": "$organization_info.lat"}}
                                                    },
                                                    {
                                                        '$cos': lat_d
                                                    },
                                                    {
                                                        '$cos': {
                                                            '$degreesToRadians': {
                                                                '$subtract': [
                                                                    {"$toDouble": "$organization_info.lon"},
                                                                    lon_baidu
                                                                ]
                                                            }
                                                        }
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                },
                                # 地球平均半径
                                6371.004
                            ]
                        }
                    }
                })
                _filter.sort({'distance': 1})
            elif condition['sort'] == '活动数':
                _filter.sort({'activity_count': -1})
            elif condition['sort'] == '报名数':
                _filter.sort({'participate_count': -1})
            elif condition['sort'] == '收藏数':
                _filter.sort({'collection_count': -1})
            else:
                _filter.sort({'end_date': -1})
        else:
            _filter.sort({'end_date': -1})
        _filter.project(activity_project)

        res = self.page_query(
            _filter, "PT_Activity", page, count)

        # 判断是否登录
        user_id = get_user_id_or_false(self.session)

        # 活动详情添加个人状态
        if len(res['result']) > 0 and user_id != False and 'id' in condition:

            # 判断该活动是否已经报名过，添加个人状态
            _filter_ps = MongoBillFilter()
            _filter_ps.match_bill((C('user_id') == user_id) & (C('activity_id') == res['result'][0]['id']))\
                .project({'_id': 0, })
            res_ps = self.query(_filter_ps, 'PT_Activity_Participate')

            if len(res_ps) > 0:
                # 已经报名
                if res['result'][0]['begin_date'] > now_date:
                    res['result'][0]['per_status'] = '已报名未开始'
                elif res['result'][0]['begin_date'] < now_date and res['result'][0]['end_date'] > now_date:
                    res['result'][0]['per_status'] = '已报名进行中'
                elif res['result'][0]['end_date'] < now_date:
                    res['result'][0]['per_status'] = '已报名已结束'
                else:
                    res['result'][0]['per_status'] = '未定义'
            else:
                if res['result'][0]['begin_date'] > now_date:
                    res['result'][0]['per_status'] = '未报名未开始'
                elif res['result'][0]['begin_date'] < now_date and res['result'][0]['end_date'] > now_date:
                    res['result'][0]['per_status'] = '未报名已开始'
                elif res['result'][0]['end_date'] < now_date:
                    res['result'][0]['per_status'] = '未报名已结束'
                else:
                    res['result'][0]['per_status'] = '未定义'

            _filter_collection = MongoBillFilter()
            _filter_collection.match_bill((C('user_id') == user_id) & (C('object') == '活动') & (C('type') == 'collection') & (C('business_id') == res['result'][0]['id']))\
                .project({'_id': 0})
            res_collection = self.query(
                _filter_collection, "PT_Service_Follow_Collection")

            if len(res_collection) > 0 and len(res['result']) > 0:
                res['result'][0]['collection_data'] = res_collection[0]
        return res

    def get_activity_sign_in_list(self, org_list, condition, page=None, count=None):
        '''查询活动签到列表'''
        keys = ['id', 'activity_name', 'begin_date', 'end_date']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id']) &
                           (C('user_id') != None) &
                           (C('activity_name').like(values['activity_name'])) &
                           (C('organization_id').inner(org_list)))\
            .lookup_bill('PT_User', 'user_id', 'id', 'user')\
            .lookup_bill('PT_Activity', 'activity_id', 'id', 'activity')

        if 'type' in condition and condition['type'] == 'mine':
            user_id = get_current_user_id(self.session)
            _filter.match_bill((C('user_id') == user_id))

        _filter.add_fields({
            'user_name': self.ao.array_elemat('$user.name', 0),
            'user_telephone': self.ao.array_elemat('$user.personnel_info.telephone', 0),
            'user_sex': self.ao.array_elemat('$user.personnel_info.sex', 0),
            'user_address': self.ao.array_elemat('$user.personnel_info.address', 0),
            'activity_name': '$activity.activity_name',
            'create_date1': self.ao.date_to_string('$create_date'),
            'modify_date1': self.ao.date_to_string('$modify_date')})\
            .project({'_id': 0,
                      'user._id': 0,
                      'activity._id': 0})

        if 'begin_date' in condition and 'end_date' in condition:
            _filter.match_bill(C('create_date') >= condition['begin_date'])
            _filter.match_bill(C('create_date') <= condition['end_date'])

        res = self.page_query(
            _filter, "PT_Activity_Sign_In", page, count)
        return res

    def get_activity_participate_list(self, org_list, condition, page=None, count=None):
        '''查询活动参与列表'''
        keys = ['id', 'name', 'user_id', 'status',
                'activity_id', 'begin_date', 'end_date']
        if 'user_id' in condition:
            condition['user_id'] = get_current_user_id(self.session)
        now_date = get_cur_time()
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('user_id') == values['user_id'])
                           & (C('id') == values['id'])
                           & (C('name').like(values['name']))
                           & (C('activity_id').like(values['activity_id']))
                           & (C('organization_id').inner(org_list)))\
            .lookup_bill('PT_Activity', 'activity_id', 'id', 'activity')\
            .lookup_bill('PT_Activity_Participate', 'activity_id', 'activity_id', 'participate')\
            .add_fields({'participate_count': self.ao.size('$participate'), })\
            .lookup_bill('PT_User', 'user_id', 'id', 'user')\
            .add_fields({
                'user_name': self.ao.array_elemat('$user.name', 0),
                'user_telephone': self.ao.array_elemat('$user.personnel_info.telephone', 0),
                'user_sex': self.ao.array_elemat('$user.personnel_info.sex', 0),
                'user_address': self.ao.array_elemat('$user.personnel_info.address', 0),
                'activity_name': self.ao.array_elemat('$activity.activity_name', 0),
                'begin_date': self.ao.array_elemat('$activity.begin_date', 0),
                'end_date': self.ao.array_elemat('$activity.end_date', 0),
                'photo': self.ao.array_elemat('$activity.photo', 0),
                'amount': self.ao.array_elemat('$activity.amount', 0),
                'activity_org_id': self.ao.array_elemat('$activity.organization_id', 0),
                'max_quantity': self.ao.array_elemat('$activity.max_quantity', 0),
                'activity_id':  self.ao.array_elemat('$activity.id', 0),
                        'create_date1': self.ao.date_to_string('$create_date'),
                        'modify_date1': self.ao.date_to_string('$modify_date')})\
            .lookup_bill('PT_User', 'activity_org_id', 'id', 'organization')\
            .add_fields({
                'organization_name': self.ao.array_elemat('$organization.name', 0)})

        if 'begin_date' in condition and 'end_date' in condition:
            _filter.match_bill(C('create_date') >= condition['begin_date'])
            _filter.match_bill(C('create_date') <= condition['end_date'])

        if 'status' in condition:
            # 报名中
            if condition['status'] == ActivityStatus.participate.value:
                # _filter.match_bill(C('begin_date') > now_date)
                print(1)
            # 进行中
            elif condition['status'] == ActivityStatus.enroll.value:
                _filter.match_bill((C('begin_date') < now_date)
                                   & (C('end_date') > now_date))
            # 已截止
            elif condition['status'] == ActivityStatus.finish.value:
                _filter.match_bill(C('end_date') > now_date)
            else:
                _filter.match_bill(now_date >= C('begin_date'))
        _filter.sort({'create_date': -1})
        _filter.project({'_id': 0,
                         'user': 0,
                         'participate': 0,
                         'activity': 0,
                         'organization': 0})
        res = self.page_query(
            _filter, "PT_Activity_Participate", page, count)

        return res

    def update_activity(self, data):
        '''# 新增/修改活动'''
        res = 'Fail'

        begin_datestr = ''

        # 开始日期和结束日期时间字符串转为时间对象
        if 'begin_date' in data and type(data['begin_date']) == str:
            begin_datestr = data['begin_date'][0:10]
            begin_date = data['begin_date'][0:10] + \
                ' '+data['begin_date'][11:19]
            data['begin_date'] = datetime.datetime.strptime(
                begin_date, '%Y-%m-%d %H:%M:%S')
        if 'end_date' in data and type(data['end_date']) == str:
            end_date = data['end_date'][0:10]+' '+data['end_date'][11:19]
            data['end_date'] = datetime.datetime.strptime(
                end_date, '%Y-%m-%d %H:%M:%S')

        if 'max_quantity' in data:
            data['max_quantity'] = int(data['max_quantity'])

        # 定义审批类型
        define_type = 'activityPublish'

        act_data = []

        # 带有id，编辑状态
        if 'id' in list(data.keys()):

            # 找出数据库里的状态
            _filter_act = MongoBillFilter()
            _filter_act.match_bill((C("id") == data['id'])).project(
                {"_id": 0})
            res_act = self.query(_filter_act, "PT_Activity")

            if len(res_act) > 0 and 'step_no' in res_act[0] and res_act[0]['step_no'] == -1:
                # 赋值待审批数据
                # 第一步
                data['step_no'] = 1
                # 待审批状态
                data['status'] = Auditstatus.unaudited.value
                # 已审核状态下的重新编辑
                return self.reChange(data, res_act, TypeId.activity.value, 'PT_Activity', define_type)

            # 进入审批流程
            if 'is_sp' in list(data.keys()):

                # 审批流程要判断这个消息提醒是否可以设置已读
                _filter_msg = MongoBillFilter()
                _filter_msg.match_bill((C('business_id') == data['id']) & (C('message_state') == MessageState.Unread.value))\
                    .sort({'create_date': -1})\
                    .project({'_id': 0})
                res_msg = self.query(
                    _filter_msg, "PT_Message")

                if len(res_msg) > 0:
                    # 设置已读
                    self.MessageManageService.set_message_already_read({
                        'id':res_msg[0]['id']
                    })

                # 统一不通过
                if data['sp_status'] == Auditstatus.reject.value:
                    # 进入审批流程
                    # 获取审批数据
                    newData = self.getSpRes(data)
                    # 公共审批流程
                    res = self.changeSpProcess(newData, TypeId.activity.value,
                                               'PT_Activity', define_type, '全部')

                    return res
                if 'step_no' in list(data.keys()):
                    # 步骤1，资料审核
                    if data['step_no'] == 1:
                        # 资料审核，由于不通过都在统一不通过，所以这里肯定是通过的
                        # 进入审批流程
                        # 获取审批数据
                        newData = self.getSpRes(data)
                        # 公共审批流程
                        res = self.changeSpProcess(newData, TypeId.activity.value,
                                                   'PT_Activity', define_type, '全部')
                    elif data['step_no'] == 2:
                        # 审核完成，由于不通过都在统一不通过，所以这里肯定是通过的
                        # 进入审批流程
                        # 获取审批数据
                        newData = self.getSpRes(data)
                        # 公共审批流程
                        res = self.changeSpProcess(newData, TypeId.activity.value,
                                                   'PT_Activity', define_type, '全部')

            else:
                bill_id = self.bill_manage_server.add_bill(
                    OperationType.update.value, TypeId.activity.value, data, 'PT_Activity')
                if bill_id:
                    res = 'Success'
        else:

            isRoomInsert = False

            # 获取当前用户
            user_id = get_current_user_id(self.session)

            # 新增一个待审批
            data['apply_user_id'] = user_id
            # 第一步
            data['step_no'] = 1
            # 待审批状态
            data['status'] = Auditstatus.unaudited.value

            # 由于app端去掉了商家，所以这里默认给一个商家

            _filter_set_role = MongoBillFilter()
            _filter_set_role.match_bill((C('principal_account_id') == user_id))\
                .project({'_id': 0})
            res_set_role = self.query(_filter_set_role, 'PT_Set_Role')

            if len(res_set_role) > 0:
                data['organization_id'] = res_set_role[0]['role_of_account_id']

            if 'activity_room_id' in data and data['activity_room_id'] != '' and data['activity_room_id'] != None:
                isRoomInsert = True
                # 判断这个时间段是否能预约
                if self.checkActivityRoomIsAllow(data['activity_room_id'], data['begin_date'], data['end_date']) == False:
                    return '该活动室当前时间段已被预约'

            # 用来找回这条数据的
            act_data = get_info(data, self.session)

            self.act_data = act_data

            # 标识新数据
            act_data['is_create'] = True

            # 接入审批流程
            res = self.changeSpProcess(act_data, TypeId.activity.value,
                                       'PT_Activity', define_type, '全部')
            if res == 'Success':
                if isRoomInsert == True:
                    # 插入活动室的预约
                    room_data = get_info({
                        'reservate_room_id': act_data['activity_room_id'],
                        'begin_date': act_data['begin_date'],
                        'end_date': act_data['end_date'],
                        'reservate_quantity': act_data['max_quantity'],
                        'contacts': act_data['contacts'],
                        'phone': act_data['phone'],
                        'user_id': act_data['apply_user_id'],
                        'reservate_date': act_data['begin_date'],
                        'organization_id': act_data['organization_id'],
                        'reservate_datestr': begin_datestr,
                    }, self.session)
                    bill_id = self.bill_manage_server.add_bill(
                        OperationType.add.value, TypeId.activityRoom.value, room_data, 'PT_Activity_Room_Reservate')

                # 插入一个消息提醒
                self.MessageManageService.add_new_message({
                    # 新闻标识
                    "business_type": 'activity',
                    # 业务ID
                    "business_id": act_data['id'],
                    # 组织机构ID
                    'organization_id': act_data['organization_id'],
                })

            # 审核是不会带活动数据的
            if res == 'Success' and 'activity_name' in data:
                real_account_data = OperationRecordObject(
                    get_current_user_id(self.session), OperationRecordType.wait_audit_activity, data['id'], data['activity_name'])
                self.OperationRecordService.insert_record(
                    real_account_data.to_dict())
        return res

    def checkActivityRoomIsAllow(self, room_id, begin_date, end_date):
        # 判断活动室是否可以预约
        # 开始时间和活动时间都不能在时间范围内
        _filter_room = MongoBillFilter()
        _filter_room.match_bill((C('reservate_room_id') == room_id) & (((C('begin_date') < begin_date) & (C('end_date') > begin_date)) | ((C('begin_date') < end_date) & (C('end_date') > end_date))))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res_room = self.query(
            _filter_room, "PT_Activity_Room_Reservate")

        if len(res_room) > 0:
            return False
        return True

    def del_activity(self, ids):
        ''' 删除活动 '''
        res = 'Fail'

        def process_func(db):
            nonlocal res
            for activity_id in ids:
                delete_data(db, 'PT_Activity', {'id': activity_id})
            res = 'Success'
        process_db(self.db_addr, self.db_port, self.db_name,
                   process_func, self.db_user, self.db_pwd)
        return res

    def participate_activity(self, condition):
        ''' 参与活动 '''
        res = 'Fail'

        activity_id = condition['id']

        user_id = get_user_id_or_false(self.session)
        if user_id == False:
            return '用户未登录！'

        now_date = get_cur_time()
        # 先判断是否已报名该活动、是否还在活动有效时间内
        _filter_activity = MongoBillFilter()
        _filter_activity.match_bill((C('id') == activity_id))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res_activity = self.query(
            _filter_activity, "PT_Activity")

        # 找不到活动
        if len(res_activity) == 0:
            return '没有找到该活动！'
        # 已结束
        if now_date > res_activity[0]['end_date']:
            return '活动已结束，无法报名！'
        # 已开始
        if now_date >= res_activity[0]['begin_date']:
            return '活动已开始，无法报名！'

        # 判断是否报名了
        _filter_participate = MongoBillFilter()
        _filter_participate.match_bill((C('activity_id') == activity_id) & (C('user_id') == user_id))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res_participate = self.query(
            _filter_participate, "PT_Activity_Participate")

        # 有报名数据
        if len(res_participate) > 0:
            return '您已报名该活动！'

        # 判断已报名数量
        _filter_participate_count = MongoBillFilter()
        _filter_participate_count.match_bill((C('activity_id') == activity_id))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res_participate_count = self.page_query(
            _filter_participate_count, "PT_Activity_Participate", 1, 1)

        max_quantity = res_activity[0]['max_quantity']
        if type(res_activity[0]['max_quantity']) == str:
            max_quantity = int(max_quantity)

        if res_participate_count['total'] >= max_quantity:
            return '该活动报名已满员！'

        data_info = get_info({
                'user_id': user_id,
                'family_ids': condition['family_ids'],
                'activity_id': activity_id,
                'status': ParticipateStatus.participate.value,
                'date': now_date,
                # 活动的组织机构ID
                'organization_id': res_activity[0]['organization_id']
            }, self.session)

        bill_id = self.bill_manage_server.add_bill(
            OperationType.add.value, TypeId.activityParticipate.value, data_info, 'PT_Activity_Participate')
        if bill_id:
            res = 'Success'
        if res == 'Success':
            # 插入一个消息提醒
            self.MessageManageService.add_new_message({
                # 活动报名标识
                "business_type": 'activity_participate',
                # 业务ID
                "business_id": data_info['id'],
                # 组织机构ID
                'organization_id': res_activity[0]['organization_id'],
            })
            real_account_data = OperationRecordObject(
                get_current_user_id(self.session), OperationRecordType.participate_activity, activity_id, res_activity[0]['activity_name'])
            self.OperationRecordService.insert_record(
                real_account_data.to_dict())
        return res

    def cancel_participate_activity(self, activity_id):
        '''取消参与活动'''
        res = 'Fail'

        user_id = get_user_id_or_false(self.session)
        if user_id == False:
            return '用户未登录！'

        now_date = get_cur_time()
        # 先判断是否已报名该活动、是否还在活动有效时间内
        _filter_activity = MongoBillFilter()
        _filter_activity.match_bill((C('id') == activity_id))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res_activity = self.query(
            _filter_activity, "PT_Activity")

        # 找不到活动
        if len(res_activity) == 0:
            return '没有找到该活动！'
        # 已开始
        if now_date >= res_activity[0]['begin_date']:
            return '取消失败，活动已开始！'

        # 判断是否报名了
        _filter_participate = MongoBillFilter()
        _filter_participate.match_bill((C('activity_id') == activity_id) & (C('user_id') == user_id))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res_participate = self.query(
            _filter_participate, "PT_Activity_Participate")

        # 没有报名数据
        if len(res_participate) == 0:
            return '未对该活动报名！'

        # 取消报名数据
        bill_id = self.bill_manage_server.add_bill(OperationType.delete.value,
                                                   TypeId.activityParticipate.value, {'id': res_participate[0]['id']}, 'PT_Activity_Participate')
        if bill_id:
            res = 'Success'
        return res

    def sign_in_activity(self, activity_id):
        ''' 活动签到 '''
        res = 'Fail'

        user_id = get_user_id_or_false(self.session)
        if user_id == False:
            return '用户未登录！'

        now_date = get_cur_time()
        # 先判断是否已报名该活动、是否还在活动有效时间内
        _filter_activity = MongoBillFilter()
        _filter_activity.match_bill((C('id') == activity_id))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res_activity = self.query(
            _filter_activity, "PT_Activity")

        # 找不到活动
        if len(res_activity) == 0:
            return '没有找到该活动！'
        # 已结束
        if now_date > res_activity[0]['end_date']:
            return '活动已结束，无法签到！'
        # 已开始
        if now_date <= res_activity[0]['begin_date']:
            return '活动未开始，无法签到！'

        # 判断是否报名了
        _filter_participate = MongoBillFilter()
        _filter_participate.match_bill((C('activity_id') == activity_id) & (C('user_id') == user_id))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res_participate = self.query(
            _filter_participate, "PT_Activity_Participate")

        # 没有报名数据
        if len(res_participate) == 0:
            return '未对该活动报名！'

        # 判断是否签到了
        _filter_signin = MongoBillFilter()
        _filter_signin.match_bill((C('activity_id') == activity_id) & (C('user_id') == user_id))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res_signin = self.query(
            _filter_signin, "PT_Activity_Sign_In")

        # 没有签到数据
        if len(res_signin) == 0:
            # 新增签到数据
            bill_id = self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.activitySignin.value, {
                    'user_id': user_id,
                    'activity_id': activity_id,
                    'date': now_date
                }, 'PT_Activity_Sign_In')
        elif len(res_signin) > 0:
            # 更新签到数据
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.activitySignin.value, {
                    'id': res_signin[0]['id'],
                    'date': now_date
                }, 'PT_Activity_Sign_In')
        if bill_id:
            res = 'Success'
        return res

    def delete_activity_participate(self, ids):
        ''' 删除参与活动 '''
        res = 'Fail'

        # 取消报名数据
        if type(ids) == list:
            for item in ids:
                bill_id = self.bill_manage_server.add_bill(OperationType.delete.value,
                                                           TypeId.activityParticipate.value, {'id': item}, 'PT_Activity_Participate')
        elif type(ids) == str:
            bill_id = self.bill_manage_server.add_bill(OperationType.delete.value,
                                                       TypeId.activityParticipate.value, {'id': ids}, 'PT_Activity_Participate')

        if bill_id:
            res = 'Success'
        return res

    def delete_activity_signin(self, ids):
        ''' 根据主键ID删除签到活动 '''
        res = 'Fail'

        # 取消报名数据
        if type(ids) == list:
            for item in ids:
                bill_id = self.bill_manage_server.add_bill(OperationType.delete.value,
                                                           TypeId.activitySignin.value, {'id': item}, 'PT_Activity_Sign_In')
        elif type(ids) == str:
            bill_id = self.bill_manage_server.add_bill(OperationType.delete.value,
                                                       TypeId.activitySignin.value, {'id': ids}, 'PT_Activity_Sign_In')

        if bill_id:
            res = 'Success'
        return res

    def delete_sign_in_activity(self, activity_id):
        '''根据活动ID取消签到活动'''
        res = 'Fail'

        user_id = get_user_id_or_false(self.session)
        if user_id == False:
            return '用户未登录！'

        now_date = get_cur_time()
        # 先判断是否已报名该活动、是否还在活动有效时间内
        _filter_activity = MongoBillFilter()
        _filter_activity.match_bill((C('id') == activity_id))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res_activity = self.query(
            _filter_activity, "PT_Activity")

        # 找不到活动
        if len(res_activity) == 0:
            return '没有找到该活动！'
        # 已结束
        if now_date > res_activity[0]['end_date']:
            return '活动已结束，无法取消签到！'
        # 已开始
        if now_date <= res_activity[0]['begin_date']:
            return '活动未开始，无法取消签到！'

        # 判断是否签到了
        _filter_signin = MongoBillFilter()
        _filter_signin.match_bill((C('activity_id') == activity_id) & (C('user_id') == user_id))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res_signin = self.query(
            _filter_signin, "PT_Activity_Sign_In")

        # 没有签到数据
        if len(res_signin) == 0:
            return '未对该活动签到！'

        # 删除签到数据
        bill_id = self.bill_manage_server.add_bill(
            OperationType.delete.value, TypeId.activitySignin.value, {
                'id': res_signin[0]['id'],
            }, 'PT_Activity_Sign_In')
        if bill_id:
            res = 'Success'
        return res

    def get_activity_type_list(self, org_list, condition, page=None, count=None):
        '''查询活动类型列表'''
        keys = ['id', 'name']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id']) & (C('name').like(values['name'])) & (C('organization_id').inner(org_list)))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res = self.page_query(
            _filter, "PT_Activity_Type", page, count)
        return res

    def update_activity_type(self, activity_type):
        '''新增/修改活动类型'''
        res = 'Fail'

        if 'id' in activity_type:
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.activityType.value, activity_type, 'PT_Activity_Type')
            if bill_id:
                res = 'Success'
        else:
            bill_id = self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.activityType.value, activity_type, 'PT_Activity_Type')
            if bill_id:
                res = 'Success'
        return res

        # def process_func(db):
        #     nonlocal res
        #     if 'id' in activity_type.keys():
        #         backVal = update_data(db, 'PT_Activity_Type', activity_type, {
        #             'id': activity_type['id']})
        #         if backVal:
        #             res = 'Success'
        #     else:
        #         # 获取流水号字段
        #         activity_type['num'] = get_serial_number(
        #             db, SerialNumberType.activity_type.value)
        #         data_info = get_info(activity_type, self.session)
        #         backVal = insert_data(db, 'PT_Activity_Type', data_info)
        #         if backVal:
        #             res = 'Success'
        # process_db(self.db_addr, self.db_port, self.db_name, process_func)
        # return res

    def del_activity_type(self, activity_type_ids):
        '''删除活动类型'''
        res = 'Fail'

        def process_func(db):
            nonlocal res
            for activity_type_id in activity_type_ids:
                _filter = MongoBillFilter()
                _filter.match((C('activity_type_id') == activity_type_id)).project(
                    {'_id': 0})
                res = self.query(_filter, "PT_Activity")
                if len(res) > 0:
                    res = '该类型已被引用，无法删除'
                else:
                    delete_data(db, 'PT_Activity_Type', {
                                'id': activity_type_id})
                    res = 'Success'
        process_db(self.db_addr, self.db_port, self.db_name,
                   process_func, self.db_user, self.db_pwd)
        return res

    def get_activity_room_list(self, org_list, condition, page=None, count=None):
        '''查询活动室列表'''
        keys = ['id', 'activity_room_name', 'organization_id', 'org_id']
        data_str = time.strftime('%Y-%m-%d', time.localtime(time.time()))
        now_date = get_cur_time()
        values = self.get_value(condition, keys)
        
        _filter = MongoBillFilter()
        _filter.lookup_bill('PT_User', 'organization_id', 'id', 'user')\
            .add_fields({
                'organization_name': '$user.name'
            })\
            .lookup_bill('PT_Activity_Room_Reservate', 'id', 'reservate_room_id', 'reservate_info')\
            .add_fields({'is_reservate': self.ao.size(self.ao.array_filter("$reservate_info", "aa", ((F('$aa.reservate_datestr') != None) & (F('$aa.reservate_datestr') == data_str)).f))})\
            .add_fields({'after_reservate': self.ao.array_filter("$reservate_info", "bb", ((F('$bb.reservate_date') != None) & (F('$bb.reservate_date') > now_date)).f)})\
            .match_bill((C('id') == values['id']) & (C('activity_room_name').like(values['activity_room_name'])) & (C('organization_id') == values['organization_id']) & (C('organization_id').inner(org_list)))

        # 获取当前的登录的用户ID的组织机构ID
        if 'org_id' in condition and condition['org_id'] == True:
            user_id = get_user_id_or_false(self.session)

            if user_id != False:
                _filter_set_role = MongoBillFilter()
                _filter_set_role.match_bill((C('principal_account_id') == user_id))\
                    .project({'_id': 0})
                res_set_role = self.query(_filter_set_role, 'PT_Set_Role')
                if len(res_set_role) > 0:
                    _filter.match_bill((C('organization_id') == res_set_role[0]['role_of_account_id']))

        _filter.sort({'create_date': -1})\
            .project({'_id': 0, 'user._id': 0, 'reservate_info._id': 0, 'after_reservate._id': 0})
        res = self.page_query(
            _filter, "PT_Activity_Room", page, count)
        return res

    def update_activity_room(self, data):
        '''新增/修改活动室'''
        res = 'Fail'

        if 'max_quantity' in data:
            data['max_quantity'] = int(data['max_quantity'])
        if 'begin_date' in data:
            data['begin_date'] = datetime.datetime.strptime(
                data['begin_date'], '%Y-%m-%dT%H:%M:%S.%fZ')
        if 'end_date' in data:
            data['end_date'] = datetime.datetime.strptime(
                data['end_date'], '%Y-%m-%dT%H:%M:%S.%fZ')

        if 'id' in list(data.keys()):
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.activityRoom.value, data, 'PT_Activity_Room')
            if bill_id:
                res = 'Success'
        else:
            bill_id = self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.activityRoom.value, data, 'PT_Activity_Room')
            if bill_id:
                res = 'Success'
        return res

    def del_activity_room(self, activity_room_ids):
        '''删除活动室'''
        res = 'Fail'

        # 删除活动室
        if type(activity_room_ids) == list:
            roomList = []
            for item in activity_room_ids:
                if self.__check_activity_room_is_reservate(item) == False:
                    return '该活动室已被预约！'
                roomList.append({'id': item})
            bill_id = self.bill_manage_server.add_bill(OperationType.delete.value,
                                                       TypeId.activityRoom.value, roomList, 'PT_Activity_Room')
        elif type(activity_room_ids) == str:
            if self.__check_activity_room_is_reservate(item) == False:
                return '该活动室已被预约！'
            bill_id = self.bill_manage_server.add_bill(OperationType.delete.value,
                                                       TypeId.activityRoom.value, {'id': activity_room_ids}, 'PT_Activity_Room')

        if bill_id:
            res = 'Success'
        return res

    # 判断活动室是否预约中
    def __check_activity_room_is_reservate(self, room_id):
        # 当前时间
        now_date = get_cur_time()
        _filter = MongoBillFilter()
        _filter.match_bill((C('reservate_room_id') == room_id) & (C('reservate_date') > now_date))\
            .sort({'create_date': -1})\
            .project({'_id': 0})
        res = self.query(
            _filter, "PT_Activity_Room_Reservate")
        if len(res) > 0:
            return False
        return True

    def get_activity_room_reservation_list(self, org_list, condition, page=None, count=None):
        '''查询活动室预约列表'''
        keys = ['id', 'reservate_room_id', 'user_id']

        # def process_func(db):
        #     nonlocal condition
        #     if 'is_oneself' in condition:
        #         condition['user_id'] = get_current_user_id(self.session)
        # process_db(self.db_addr, self.db_port, self.db_name, process_func)

        if 'is_oneself' in condition:
            condition['user_id'] = get_current_user_id(self.session)
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id'])
                           & (C('reservate_room_id').like(values['reservate_room_id']))
                           & (C('user_id') == values['user_id'])
                           & (C('organization_id').inner(org_list)))\
            .lookup_bill('PT_Activity_Room', 'reservate_room_id', 'id', 'activityRoom')\
            .lookup_bill('PT_User', 'user_id', 'id', 'user')\
            .add_fields({
                'activity_room_name': '$activityRoom.activity_room_name',
                'photo': "$activityRoom.photo",
                'open_date': '$activityRoom.open_date',
                'address': '$activityRoom.address',
                'organization_name': '$user.name',
                # 'reservate_date2': self.ao.date_to_string('$reservate_date'),
            })\
            .sort({'create_date': -1})\
            .project({'_id': 0, 'user._id': 0, 'activityRoom._id': 0})
        res = self.page_query(
            _filter, "PT_Activity_Room_Reservate", page, count)
        return res

    def update_activity_room_reservation(self, data):
        '''# 新增/修改活动室预约'''
        res = 'Fail'

        # 查询是否已经预约
        _filter_main = MongoBillFilter()
        _filter_main.match_bill((C('reservate_room_id') == data['reservate_room_id'])
                                & (C('reservate_datestr') == data['reservate_datestr'])).project({'_id': 0})
        main_data = self.query(
            _filter_main, 'PT_Activity_Room_Reservate')

        datakey = list(data.keys())

        # 有当前活动室的当天日子的预约
        if len(main_data) > 0:
            # 是否该数据的编辑操作
            if 'id' not in datakey or ('id' in datakey and main_data[0]['id'] != data['id']):
                # 已经预约
                return '该活动室该时间段已被预约！'

        if 'reservate_date' in data and type(data['reservate_date']) == str:
            data['reservate_date'] = datetime.datetime.strptime(
                data['reservate_date'], '%Y-%m-%dT%H:%M:%S.%fZ')

        if 'id' in datakey:
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.activityRoomReservation.value, data, 'PT_Activity_Room_Reservate')
            if bill_id:
                res = 'Success'
        else:

            data['user_id'] = get_current_user_id(self.session)

            bill_id = self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.activityRoomReservation.value, data, 'PT_Activity_Room_Reservate')
            if bill_id:
                res = 'Success'
        return res

    def del_activity_room_reservation(self, ids):
        '''删除活动室预约'''
        res = 'Fail'

        # 删除活动室预约
        if type(ids) == list:
            delList = []
            for item in ids:
                delList.append({'id': item})
            bill_id = self.bill_manage_server.add_bill(OperationType.delete.value,
                                                       TypeId.activityRoomReservation.value, delList, 'PT_Activity_Room_Reservate')
        elif type(ids) == str:
            bill_id = self.bill_manage_server.add_bill(OperationType.delete.value,
                                                       TypeId.activityRoomReservation.value, {'id': ids}, 'PT_Activity_Room_Reservate')

        if bill_id:
            res = 'Success'
        return res

    def reservate_activity_room(self, activity_room_id, reservate_date):
        ''' 预约活动室 '''
        res = 'Fail'
        if reservate_date:
            reservate_date = reservate_date[0:10]

        def process_func(db):
            nonlocal res
            activity_room = {}
            activity_room['activity_room_id'] = activity_room_id
            activity_room['reservate_date'] = reservate_date
            activity_room['user_id'] = get_current_user_id(self.session)
            data = find_data(db, 'PT_Activity_Room_Reservate', activity_room)
            if len(data) > 0:
                res = '当前时间你已预约'
            else:
                data_info = get_info(activity_room, self.session)
                backVal = insert_data(
                    db, 'PT_Activity_Room_Reservate', data_info)
                if backVal:
                    res = 'Success'
        process_db(self.db_addr, self.db_port, self.db_name,
                   process_func, self.db_user, self.db_pwd)
        return res

    def get_activity_comment_list(self, org_list, condition, page=None, count=None):
        '''查询评论列表'''

        keys = ['id', 'name']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id'])
                           & (C('type_id') == '42ec6dd2-c002-11e9-a315-f45fc101cb0b')
                           & (C('name').like(values['name']))
                           & (C('organization_id').inner(org_list)))

        if 'begin_date' in condition and 'end_date' in condition:
            _filter.match_bill(C('create_date') >= condition['begin_date'])
            _filter.match_bill(C('create_date') <= condition['end_date'])

        _filter.sort({'create_date': -1})
        _filter.project({
            '_id': 0,
        })

        res = self.page_query(
            _filter, "PT_Comment", page, count)

        return res

    def get_activity_information_list(self, org_list, condition, page=None, count=None):
        '''查询活动汇总信息列表'''
        monthData = condition['month'].split('-')
        thisMonthDates = calendar.monthrange(
            int(monthData[0]), int(monthData[1]))

        begin_date = str(condition['month']) + '-01 00:00:00'
        end_date = str(condition['month']) + '-' + \
            str(thisMonthDates[1]) + ' 23:59:59'
        begin_date = datetime.datetime.strptime(
            begin_date, "%Y-%m-%d %H:%M:%S")
        end_date = datetime.datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S")

        newCondition = {}
        newCondition['begin_date'] = begin_date
        newCondition['end_date'] = end_date
        return {
            # 获取活动列表
            'activity_list': self.get_activity_list(org_list, newCondition, 1, 99),
            # 获取签到列表
            'signin_list': self.get_activity_sign_in_list(org_list, newCondition, 1, 99),
            # 获取报名列表
            'participate_list': self.get_activity_participate_list(org_list, newCondition, 1, 99),
            # 获取评论列表
            'comment_list': self.get_activity_comment_list(org_list, newCondition, 1, 99),
        }

    # 已审批之后的重新编辑
    def reChange(self, new_data, old_data, typeId, ptdb, define_type):

        # 先把审批表的数据都设置valid
        _filter_process = MongoBillFilter()
        _filter_process.match_bill(
            (C('business_id') == old_data[0]['id'])).project({'_id': 0})
        process_data = self.query(
            _filter_process, 'PT_Approval_Process')

        if len(process_data) > 0:
            for item in process_data:
                bill_id = self.bill_manage_server.add_bill(
                    OperationType.delete.value, TypeId.approvalProcess.value, {'id': item['id']}, 'PT_Approval_Process')

        # 标识二次编辑状态
        new_data['is_rechange'] = True

        # 把旧数据赋值给新数据

        # 接入审批流程
        res = self.changeSpProcess(new_data, typeId,
                                   ptdb, define_type, '全部')

        return res

    # 修改审批流程操作
    def changeSpProcess(self, data, typeId, table, stepType, roleName, extra=[], callback=False):

        res = 'Fail'

        # 如果带有id，编辑状态
        if 'id' in data.keys() and 'is_create' not in data.keys() and 'is_rechange' not in data.keys():

            role_id = get_current_role_id(self.session)
            user_id = get_current_user_id(self.session)

            _filter_process = MongoBillFilter()
            _filter_process.match_bill((C('business_id') == data['id']) & (
                C('approval_user_id') == role_id) & (C('step_no') == data['step_no'])).project({'_id': 0})
            process_data = self.query(
                _filter_process, 'PT_Approval_Process')

            if len(process_data) == 0:
                return '请刷新页面重试！'

            if len(process_data) > 0 and 'sp_status' in data.keys():
                if process_data[0]['status'] != Auditstatus.unaudited.value:
                    return '无法重复审核'
                if data['sp_status'] == Auditstatus.adopt.value:
                    # 审批状态
                    process_data[0]['status'] = data['sp_status']
                    # 主数据
                    data['status'] = data['status']

                    _filter_process_length = MongoBillFilter()
                    _filter_process_length.match_bill(
                        (C('business_id') == data['id'])).project({'_id': 0})
                    process_data_length = len(self.query(
                        _filter_process_length, 'PT_Approval_Process'))

                    if process_data_length != data['step_no']:
                        # 如果不是最后一步，就变成下一步
                        data['step_no'] = data['step_no'] + 1
                    else:
                        # -1表示完成了
                        data['step_no'] = -1
                        process_data[0]['step_no'] = -1

                elif data['sp_status'] == '不通过':
                    # 审批状态
                    process_data[0]['status'] = data['sp_status']
                    # 主数据
                    data['status'] = data['status']
                elif data['sp_status'] == '打回':
                    # 审批状态
                    process_data[0]['status'] = data['sp_status']
                    # 主数据
                    data['status'] = data['status']

            # 删掉审批结果和审批可能附带的
            if 'sp_status' in data:
                del(data['sp_status'])
            if 'sp_msg' in data:
                process_data[0]['opinion'] = [data['sp_msg']]

            # 补充审核操作人
            process_data[0]['proccess_user_id'] = user_id

            # 有额外添加的数据
            if len(extra) > 0:
                for index in extra:
                    data[index] = extra[index]

            # 进入审批状态，并修改主数据
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, typeId, [data, process_data[0]], [table, 'PT_Approval_Process'])
            if bill_id:
                res = 'Success'

            if callback:
                callback()
        else:
            # 新增状态

            # 操作类型，默认新增
            opt = OperationType.add.value

            # 二次编辑，主数据update,其他数据新增
            if 'is_rechange' in data:
                opt = OperationType.update.value
                del(data['is_rechange'])

            # 新数据，保证外部id完整
            if 'is_create' in data:
                del(data['is_create'])

            # 主数据
            data_info = get_info(data, self.session)

            # 找到Approval_Define表的规则
            _filter = MongoBillFilter()
            _filter.match_bill((C('approval_type') == stepType) & (C('type') == roleName))\
                .project({'_id': 0})
            res_define = self.query(_filter, 'PT_Approval_Define')
            if len(res_define) > 0 and len(res_define[0]['approval_list']) > 0:
                process_data_list = []
                table_list = []
                for approval in res_define[0]['approval_list']:
                    process_data = {"define_id": res_define[0]['id'], "business_id": data_info['id'], "approval_user_id":
                                    approval['approval_user_id'], "step_no": approval['step_no'], "opinion": [], "status": "待审批"}

                    process_data_list.append(
                        get_info(process_data, self.session))
                    table_list.append('PT_Approval_Process')

                # process_data_list.append(data_info)
                # table_list.append(table)

                # 进入审批状态，并新增主数据
                bill_id = self.bill_manage_server.add_bill(
                    OperationType.add.value, typeId, process_data_list, table_list)
                if bill_id:
                    bill_id2 = self.bill_manage_server.add_bill(
                        opt, typeId, data_info, table)
                    if bill_id2:
                        res = 'Success'
            else:
                return '无发布权限'
        return res

    def getSpRes(self, data):
        # 审批流程的数据
        spData = {
            'id': data['id'],
            'sp_status': data['sp_status'],
            'status': data['status'],
            'step_no': data['step_no'],
        }
        if 'sp_msg' in data:
            spData['sp_msg'] = data['sp_msg']
        return spData
